import type { EChartsOption } from "echarts";
import { useRouterStoreHook } from "@/store/modules/router";
import { getFabPCWEConsume, getFabWaterConsume, getFabWaterEmissionConsume, getFabTotalEConsume } from "@/api/modules/fab";
import type { SubjectType } from "@/utils/types";

const routerStore = useRouterStoreHook();

/**
 * @description: 折线图配置
 * @param {Boolean} flag       是否为双纵坐标，默认为false，即单纵坐标
 * @param {String} unit        单位
 * @param {Array} xAxisData    横坐标
 * @param {Array} specData     第一组纵坐标 SPEC目标值
 * @param {Array} usedData     第一组纵坐标 实际值
 * @param {Array} upperData    第一组纵坐标 SPEC上限值
 * @param {Array} lowerData    第一组纵坐标 SPEC下限值
 * @param {Array} specData2    第二组纵坐标 SPEC目标值
 * @param {Array} usedData2    第二组纵坐标 实际值
 * @param {Array} upperData2   第二组纵坐标 SPEC上限值
 * @param {Array} lowerData2   第二组纵坐标 SPEC下限值
 * @param {String} seriesName  当前 series name
 * @return {*}
 */
const labelLayoutLineChartFn = (
  flag = false,
  unit: string,
  xAxisData?: Array<string>,
  specData?: Array<number>,
  usedData?: Array<number>,
  upperData?: Array<number>,
  lowerData?: Array<number>,
  specData2?: Array<number>,
  usedData2?: Array<number>,
  upperData2?: Array<number>,
  lowerData2?: Array<number>,
  seriesName?: string
): CommonEcharts.CommonEchartsOption => {
  function getSeriesOptionsItem(name?: string, data?: Array<number>, color?: string, flag = false, unit = ""): any {
    const s = {
      name,
      unit,
      type: "line",
      symbol: "circle",
      symbolSize: 4,
      data,
      itemStyle: {
        color
      },
      lineStyle: {
        color,
        width: 1
      }
    };
    if (flag) s["yAxisIndex"] = 1;
    return s;
  }

  function getSeriesOptions(flag?: boolean, seriesName?: string): Array<any> {
    if (flag) {
      if (seriesName && seriesName.includes("电压")) {
        return [
          getSeriesOptionsItem("电压实际用量", usedData, "#3B82F6", false, "V"),
          getSeriesOptionsItem("电流实际用量", usedData2, "#6f6f6f", true, "A"),
          getSeriesOptionsItem("电压SPEC目标值", specData, "#70B602", false, "V"),
          getSeriesOptionsItem("电压SPEC上限", upperData, "#F1999B", false, "V"),
          getSeriesOptionsItem("电压SPEC下限", lowerData, "#F59A23", false, "V")
        ];
      } else if (seriesName && seriesName.includes("电流")) {
        return [
          getSeriesOptionsItem("电压实际用量", usedData, "#3B82F6", false, "V"),
          getSeriesOptionsItem("电流实际用量", usedData2, "#6f6f6f", true, "A"),
          getSeriesOptionsItem("电流SPEC目标值", specData2, "#70B602", true, "A"),
          getSeriesOptionsItem("电流SPEC上限", upperData2, "#F1999B", true, "A"),
          getSeriesOptionsItem("电流SPEC下限", lowerData2, "#F59A23", true, "A")
        ];
      } else {
        return [
          getSeriesOptionsItem("电压实际用量", usedData, "#3B82F6", false, "V"),
          getSeriesOptionsItem("电流实际用量", usedData2, "#6f6f6f", true, "A")
        ];
      }
    } else {
      return [
        getSeriesOptionsItem("实际用量", usedData, "#6f6f6f"),
        getSeriesOptionsItem("SPEC目标值", specData, "#70B602"),
        getSeriesOptionsItem("SPEC上限", upperData, "#F1999B"),
        getSeriesOptionsItem("SPEC下限", lowerData, "#F59A23")
      ];
    }
  }

  function getTooltip(flag?: boolean): any {
    const tooltip = {
      trigger: "axis",
      triggerOn: "mousemove",
      hideDelay: 100,
      axisPointer: {
        type: "cross",
        axis: "x"
      }
    };
    if (flag) {
      tooltip["formatter"] = function (params) {
        let tooltipHtml = `时间：${params[0].name}`;
        params.forEach(item => {
          const { seriesName, marker, value } = item;
          let i = `<br/>${marker} ${seriesName}： ${value}`;
          if (seriesName && seriesName.includes("电压")) {
            i += " V";
          } else if (seriesName && seriesName.includes("电流")) {
            i += " A";
          }
          tooltipHtml += i;
        });
        return tooltipHtml;
      };
    }
    return tooltip;
  }

  function getYAxis(flag?: boolean): any | Array<any> {
    if (flag) {
      return [
        {
          name: "电压 / V",
          type: "value"
        },
        {
          name: "电流 / A",
          type: "value",
          nameLocation: "end",
          alignTicks: true
        }
      ];
    } else {
      return {
        name: `单位 / ${unit}`,
        type: "value",
        axisPointer: {
          show: true,
          type: "line",
          label: {
            show: true
          },
          lineStyle: {
            type: "dashed",
            color: "#979797"
          }
        }
      };
    }
  }

  function getCommonOptions(flag?: boolean): EChartsOption {
    const title = {
      left: -5,
      top: -6,
      subtextStyle: {
        color: "#333"
      }
    };
    const legend = { show: true };
    const grid = {
      left: 0,
      right: 16,
      top: 40,
      bottom: 0,
      containLabel: true
    };
    const xAxis: any = {
      type: "category",
      boundaryGap: false,
      data: xAxisData,
      axisPointer: {
        show: true,
        type: "line",
        label: {
          show: true
        },
        lineStyle: {
          type: "dashed",
          color: "#979797"
        }
      }
    };
    const tooltip: any = getTooltip(flag);
    const yAxis: any | Array<any> = getYAxis(flag);
    return {
      title,
      tooltip,
      legend,
      grid,
      xAxis,
      yAxis
    };
  }
  const commonOptions: EChartsOption = getCommonOptions(flag);
  const series: Array<any> = getSeriesOptions(flag, seriesName);
  const options: EChartsOption = { ...commonOptions, series };
  return options;
};

/**
 * @description: 获取参数
 * @return {*}
 */
export const getParams = (className: string): { className?: string; gasName?: string } => {
  const { activeViceMenu: gasName } = routerStore;
  if (className === "GAS") {
    return { className, gasName };
  } else {
    return { className };
  }
};

/**
 * @description: 获取某项数据
 * @param {Array} list 需要 echarts 渲染的数据（数组）
 * @param {*} key 所需获取数据的 key 默认为 hour
 * @return {*}
 */
export const formatEchartsItemData = (list?: Array<any> | null, key = "hour"): Array<string> => {
  if (!list?.length) return [];
  return list.map(item => item[key]);
};

/**
 * @description: 格式化PCW用量数据（机械课）
 * @param {Array} res
 * @return {*}
 */
const formatPCWEConsumeMEData = (res?: Record<string, any> | null) => {
  const { hourValueList, specMaxNum, specMinNum, specNum } = res;
  const xAxisData: Array<string> = formatEchartsItemData(hourValueList, "hourStr");
  const specData: Array<number> = [];
  const usedData: Array<number> = [];
  const upperData: Array<number> = [];
  const lowerData: Array<number> = [];
  hourValueList.forEach(item => {
    const { value = 0 } = item;
    specData.push(specNum);
    usedData.push(value);
    upperData.push(specMaxNum);
    lowerData.push(specMinNum);
  });
  return { xAxisData, specData, usedData, upperData, lowerData };
};

/**
 * @description: 格式化PCW用量数据（水课）
 * @param {Array} res
 * @return {*}
 */
const formatWaterConsumeMEData = (res?: Record<string, any>) => {
  const { hourValueList = [], specMaxNum = 0, specMinNum = 0, specNum = 0 } = res;
  const xAxisData: Array<string> = hourValueList.map(item => item.hourStr);
  const specData: Array<number> = [];
  const usedData: Array<number> = [];
  const upperData: Array<number> = [];
  const lowerData: Array<number> = [];
  hourValueList.forEach(item => {
    const { value = 0 } = item;
    specData.push(specNum);
    usedData.push(value);
    upperData.push(specMaxNum);
    lowerData.push(specMinNum);
  });
  return { xAxisData, specData, usedData, upperData, lowerData };
};

/**
 * @description: 格式化总体供电数据（电课）
 * @param {Array} res
 * @return {*}
 */
const formatTotalEConsumeEData = (res?: Record<string, any> | null) => {
  const { current, voltage } = res;
  const xAxisData: Array<string> = formatEchartsItemData(current.hourValueList, "hourStr");
  const specData: Array<number> = [];
  const usedData: Array<number> = [];
  const upperData: Array<number> = [];
  const lowerData: Array<number> = [];
  const specData2: Array<number> = [];
  const usedData2: Array<number> = [];
  const upperData2: Array<number> = [];
  const lowerData2: Array<number> = [];
  // 电压
  for (const item of voltage.hourValueList) {
    const { value } = item;
    const { specMaxNum, specMinNum, specNum } = voltage;
    usedData.push(value);
    specData.push(specNum);
    upperData.push(specMaxNum);
    lowerData.push(specMinNum);
  }
  // 电流
  for (const item of current.hourValueList) {
    const { value } = item;
    const { specMaxNum, specMinNum, specNum } = current;
    usedData2.push(value);
    specData2.push(specNum);
    upperData2.push(specMaxNum);
    lowerData2.push(specMinNum);
  }
  return {
    xAxisData,
    specData,
    usedData,
    upperData,
    lowerData,
    specData2,
    usedData2,
    upperData2,
    lowerData2
  };
};

/**
 * @description: 判断传入 echarts 的数据（数组）是否真的为空，即所有项目都为 null
 * @param {Array} d
 * @return {*}
 */
export const isActuallyEmpty = (d?: Array<string | number> | null): boolean => {
  if (!d || !d.length) return true;
  const flag = d.reduce((pre, cur) => {
    if (cur || cur === 0) {
      pre = false;
    }
    return pre;
  }, true);
  if (flag) {
    return true;
  }
  return false;
};

/**
 * @description: 获取PCW用量echarts配置（机械课+水课）
 * @param {SubjectType} subject
 * @param {string} unit
 * @param {boolean} flag
 * @return {*}
 */
export const useLabelLayoutMachineConsumeMEFn = async (
  subject: SubjectType,
  unit: string,
  flag: boolean = false
): Promise<CommonEcharts.CommonEchartsOption> => {
  let res = null;
  if (flag) {
    res = await getFabWaterConsume();
    if (!res) return null;
    const { xAxisData, specData, usedData, upperData, lowerData } = formatWaterConsumeMEData(res);
    if (
      isActuallyEmpty(xAxisData) ||
      (isActuallyEmpty(specData) && isActuallyEmpty(usedData) && isActuallyEmpty(upperData) && isActuallyEmpty(lowerData))
    )
      return null;
    return labelLayoutLineChartFn(false, unit, xAxisData, specData, usedData, upperData, lowerData);
  } else {
    const params = getParams(subject);
    res = await getFabPCWEConsume(params);
    if (!res?.hourValueList?.length) return null;
    const { xAxisData, specData, usedData, upperData, lowerData } = formatPCWEConsumeMEData(res);
    if (
      isActuallyEmpty(xAxisData) ||
      (isActuallyEmpty(specData) && isActuallyEmpty(usedData) && isActuallyEmpty(upperData) && isActuallyEmpty(lowerData))
    )
      return null;
    return labelLayoutLineChartFn(false, unit, xAxisData, specData, usedData, upperData, lowerData);
  }
};

/**
 * @description: 获取总体供电echarts配置（电课）
 * @param {Array} res
 * @return {*}
 */
export const useLabelLayoutTotalEConsumeEFn = async (unit: string, seriesName?: string): Promise<CommonEcharts.CommonEchartsOption> => {
  const res = await getFabTotalEConsume();
  if (!res) return null;
  const { xAxisData, specData, usedData, upperData, lowerData, specData2, usedData2, upperData2, lowerData2 } = formatTotalEConsumeEData(res);
  if (
    isActuallyEmpty(xAxisData) ||
    (isActuallyEmpty(specData) &&
      isActuallyEmpty(usedData) &&
      isActuallyEmpty(upperData) &&
      isActuallyEmpty(lowerData) &&
      isActuallyEmpty(specData2) &&
      isActuallyEmpty(usedData2) &&
      isActuallyEmpty(upperData2) &&
      isActuallyEmpty(lowerData2))
  )
    return null;

  return labelLayoutLineChartFn(
    true,
    unit,
    xAxisData,
    specData,
    usedData,
    upperData,
    lowerData,
    specData2,
    usedData2,
    upperData2,
    lowerData2,
    seriesName
  );
};

/**
 * @description: 24小时机台废水排放量（水课）
 * @param {string} unit
 * @return {*}
 */
export const useLabelLayoutWaterEmissionFn = async (unit: string): Promise<CommonEcharts.CommonEchartsOption> => {
  const res = await getFabWaterEmissionConsume();
  if (!res) return null;
  const { hourValueList } = res;
  const xAxisData = hourValueList?.map(item => item.hourStr);
  const seriesData = hourValueList?.map(item => item.value);
  if (isActuallyEmpty(xAxisData) || isActuallyEmpty(seriesData)) return null;
  const series = [
    {
      type: "line",
      symbol: "circle",
      data: seriesData,
      itemStyle: {
        color: "#3B82F6"
      }
    }
  ];
  const option = labelLayoutLineChartFn(false, unit, xAxisData, [], seriesData, [], []);
  return { ...option, series };
};
